package org.ands.client.ala;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.ands.apps.PropertyHelper;
import org.ands.crosswalk.CrossWalkEntry;
import org.ands.crosswalk.CrossWalkEntryRetrieverCSV;
import org.ands.data.Contents;
import org.ands.data.ContentsHelper;
import org.ands.data.IClientContentsRetriever;
import org.ands.json.JsonHelper;
import org.ands.json.JsonHelperFromUri;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;

// TODO: Auto-generated Javadoc
/**
 * The Class ContentsRetrieverALA.
 */
public class ContentsRetrieverALA implements IClientContentsRetriever {
	
	/**
	 * Constructs a list of XMLContents objects from the xpaths-and-value pairs
	 * that it determines from Atlas of Living Australia json.
	 * The list contains many XMLContents objects that represent many DataResource
	 * objects and many related DataProvider objects that are associated with
	 * each DataResource.
	 *
	 * @param propertyHelper the property helper
	 * @return          			If successful, a list of XMLContents objects
	 * constructed from the values from ALA;
	 * <code>null</code> otherwise.
	 * @throws Exception the exception
	 * @see   	Contents
	 * @since     1.0
	 */
	@Override
	public Map<Integer, List<Contents>> getXmlContentsFromClient(final PropertyHelper propertyHelper) 
					throws Exception{
		
		final String uriAllDataResources = propertyHelper.getProperty("DR_URI", true);
		if((uriAllDataResources == null) || (uriAllDataResources.isEmpty())){
			throw new Exception("Requires valid uri");
		}
		
		final String dataResourceCrossWalkFile = propertyHelper.getProperty("DR_COLLECTION_CROSSWALK", true);
		if((dataResourceCrossWalkFile == null) || (dataResourceCrossWalkFile.isEmpty())){
			throw new Exception("Requires valid collection crosswalk filename");
		}
		
		final String partyCrossWalkFile = propertyHelper.getProperty("DP_PARTY_CROSSWALK", true);
		if((partyCrossWalkFile == null) || (partyCrossWalkFile.isEmpty())){
			System.out.println("Not including parties because crosswalk for parties not provided");
		}
		
		String jsonAllDataResources = JsonHelper.contentFromUri(uriAllDataResources);
		assert(jsonAllDataResources != null);
		assert(jsonAllDataResources.length() > 0);
		
		CrossWalkEntryRetrieverCSV crossWalkEntryRetrieverCSV = new CrossWalkEntryRetrieverCSV();
		// Map where int is the index to the registryObject (starting at one) and the list of XmlContents
		// is all of the XmlContent objects per registryObject at the index
		Map<Integer, List<Contents> > xmlContentsAllRegistryObjectsMap = new HashMap<Integer, List<Contents> >();
		
		ArrayNode drMetadataNodeArray = JsonHelper.arrayNodeFromString(jsonAllDataResources);
		Integer drCount = 1; // Accumulate count of DataResources // Used for index on RegistryObject
		Integer dpCount = 1; // Accumulate count of DataProviders // Used for index on RegistryObject
		ArrayList<CrossWalkEntry> dataResourceCrossWalkEntryList = crossWalkEntryRetrieverCSV.getCrossWalkEntryListFromFile(dataResourceCrossWalkFile);
		assert((dataResourceCrossWalkEntryList != null) && (!dataResourceCrossWalkEntryList.isEmpty()));
		
		ArrayList<CrossWalkEntry> partyCrossWalkEntryList = null;
		if(partyCrossWalkFile != null && !partyCrossWalkFile.isEmpty()){
			partyCrossWalkEntryList = crossWalkEntryRetrieverCSV.getCrossWalkEntryListFromFile(partyCrossWalkFile);
			assert((partyCrossWalkEntryList != null) && (!partyCrossWalkEntryList.isEmpty()));
		}
		
		
		int count = 0;
		for(JsonNode drMetadataNode: drMetadataNodeArray){
			
			if (count++ > 5){
				return xmlContentsAllRegistryObjectsMap; // for testing only
			}
			
			JsonHelper drMetadataHelper = new JsonHelper(drMetadataNode);
			
			List<String> drUriValueList = drMetadataHelper.contentListFromPath("uri"); 
			assert(drUriValueList.size() == 1);
			String drUriValue = drUriValueList.get(0);
			System.out.println("Uri for data resource ["+drUriValue+"].");
			
			List<String> drUidValueList = drMetadataHelper.contentListFromPath("uid"); 
			assert(drUidValueList.size() == 1);
			String drUidValue = drUidValueList.get(0);
			System.out.println("Uid for data resource ["+drUidValue+"].");
			
			JsonHelperFromUri drHelper = new JsonHelperFromUri(drUriValue);
			
			try{
				ArrayList<Contents> dpList = null;
				if(partyCrossWalkFile != null && !partyCrossWalkFile.isEmpty()){
					assert((partyCrossWalkEntryList != null) && (!partyCrossWalkEntryList.isEmpty()));
					List<String> dpUriValueList = drHelper.contentListFromPathList(Arrays.asList("provider", "uri"));
					assert(dpUriValueList.size() == 1);
					String dpUriValue = dpUriValueList.get(0);
					
					if((dpUriValue == null) || (dpUriValue.isEmpty())){
						System.out.println("No data provider URI available from data resource ["+drUidValue+"].");
						assert(false);
						continue;
					}
					System.out.println("Uri for data provider ["+dpUriValue+"].");
					JsonHelperFromUri dpHelper = new JsonHelperFromUri(dpUriValue);
					dpList = ContentsHelper.xmlContentsFromTree(dpHelper, partyCrossWalkEntryList, dpCount);
					drCount = dpCount + 1;
				}
				
				// Provider added ok, so add the collection:
				ArrayList<Contents> drList = ContentsHelper.xmlContentsFromTree(drHelper, dataResourceCrossWalkEntryList, drCount);
				
				assert(drList != null);
				assert(!drList.isEmpty());
			
				// So far so good for data resource, so add both provider and resource
				if(partyCrossWalkFile != null && !partyCrossWalkEntryList.isEmpty()){
					assert(dpList != null);
					assert(!dpList.isEmpty());
					xmlContentsAllRegistryObjectsMap.put(dpCount, dpList);
					dpCount = dpCount + 2;
				}
				
				xmlContentsAllRegistryObjectsMap.put(drCount, drList);
				drCount++;
				
			}catch(Exception e){
				System.err.println("Failed to obtain required data resource ["+drUidValue+"] - Exception: ["+e.getMessage()+"].\n");
				//assert(false);
			}
		}
		
		if(xmlContentsAllRegistryObjectsMap.size() <= 0){
			throw new Exception("Unable to create XMLContents from uri ["+uriAllDataResources+"].");
		}
		
		return xmlContentsAllRegistryObjectsMap;
		
	}
	
	/* (non-Javadoc)
	 * @see org.ands.data.IContentsRetriever#getOutFileFromConfig(org.ands.apps.PropertyHelper)
	 */
	@Override
	public String getOutFileFromConfig(final PropertyHelper propertyHelper)
			throws Exception {
		
		return propertyHelper.getProperty("RIF_CS_XML_OUT_ALA_DR_DP", true);
	}
		
}

